﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using SharedGenomics.Annotations;
using SharedGenomics.Workbench.Annotations;

using Rhino.Mocks;
using Rhino.Mocks.Constraints;

namespace SharedGenomics.Workbench.Tests.Annotations
{
    [TestClass]
    public class AnnotationManagerTests
    {
        private MockRepository mocks;
        private ActiveAnnotationsPersistanceManager prefsManager;

        [TestInitialize]
        public void Setup()
        {
            this.mocks = new MockRepository();
            this.prefsManager = this.mocks.DynamicMock<ActiveAnnotationsPersistanceManager>();
        }

        [TestCleanup]
        public void TearDown()
        {
            this.mocks.VerifyAll();
        }

        [TestMethod]
        public void ShouldLoadPreferences()
        {
            this.prefsManager.Expect(pm => pm.Load()).Return(AnnotationDescriptor.AllAnnotationDescriptors.ToDictionary(ad => ad, ad => true));
            this.mocks.ReplayAll();

            var manager = new AnnotationManager(this.prefsManager);
            Assert.IsTrue(manager.AnnotationActivationStatuses.All(kvp => kvp.Value));
        }

        [TestMethod]
        public void ShouldDeactivateAllAnnotations()
        {
            this.prefsManager.Expect(pm => pm.Load()).Return(AnnotationDescriptor.AllAnnotationDescriptors.ToDictionary(ad => ad, ad => true));
            this.mocks.ReplayAll();

            var manager = new AnnotationManager(this.prefsManager);
            manager.DeactivateAll();

            Assert.IsTrue(manager.AnnotationActivationStatuses.All(kvp => !kvp.Value));
        }

        [TestMethod]
        public void ShouldActivateAllAnnotations()
        {
            this.prefsManager.Expect(pm => pm.Load()).Return(AnnotationDescriptor.AllAnnotationDescriptors.ToDictionary(ad => ad, ad => true));
            this.mocks.ReplayAll();

            var manager = new AnnotationManager(this.prefsManager);
            manager.DeactivateAll();
            manager.ActivateAll();

            Assert.IsTrue(manager.AnnotationActivationStatuses.All(kvp => kvp.Value));
        }

        [TestMethod]
        public void ShouldReturnActiveAnnotationTypes()
        {
            this.prefsManager.Expect(pm => pm.Load()).Return(AnnotationDescriptor.AllAnnotationDescriptors.ToDictionary(ad => ad, ad => true));
            this.mocks.ReplayAll();

            var manager = new AnnotationManager(this.prefsManager);
            manager.ActivateAll();

            CollectionAssert.AreEqual(manager.AnnotationActivationStatuses.Select(kvp => kvp.Key.AnnotationType).ToArray(), manager.ActiveAnnotationTypes.ToArray());
        }

        [TestMethod]
        public void ShouldActivateAnnotationType()
        {
            this.prefsManager.Expect(pm => pm.Load()).Return(AnnotationDescriptor.AllAnnotationDescriptors.ToDictionary(ad => ad, ad => true));
            this.mocks.ReplayAll();

            var manager = new AnnotationManager(this.prefsManager);
            manager.DeactivateAll();

            var activation = manager.AnnotationActivationStatuses.First();
            Type annotationType = activation.Key.AnnotationType;

            manager.SetAnnotationActive(annotationType, true);
            Assert.AreEqual(annotationType, manager.ActiveAnnotationTypes.First());
        }

        [TestMethod]
        public void ShouldDeactivateAnnotationType()
        {
            this.prefsManager.Expect(pm => pm.Load()).Return(AnnotationDescriptor.AllAnnotationDescriptors.ToDictionary(ad => ad, ad => true));
            this.mocks.ReplayAll();

            var manager = new AnnotationManager(this.prefsManager);
            manager.ActivateAll();

            var activation = manager.AnnotationActivationStatuses.First();
            Type annotationType = activation.Key.AnnotationType;

            manager.SetAnnotationActive(annotationType, false);
            Assert.IsFalse(manager.ActiveAnnotationTypes.Contains(annotationType));
        }

        [TestMethod]
        public void ShouldSave()
        {
            List<AnnotationDescriptor> descriptors = new List<AnnotationDescriptor>
            {
                AnnotationDescriptor.GetDescriptorForKey(AnnotationKey.GoogleSearch),
                AnnotationDescriptor.GetDescriptorForKey(AnnotationKey.NcbiSummary)
            };

            this.prefsManager.Expect(pm => pm.Load()).Return(descriptors.ToDictionary(ad => ad, ad => true));
            this.prefsManager.Expect(pm => pm.Save(null)).IgnoreArguments().Constraints(List.Equal(new[] { typeof(GoogleSearchAnnotation) }));
            this.mocks.ReplayAll();

            var manager = new AnnotationManager(this.prefsManager);
            manager.SetAnnotationActive(typeof(NcbiAnnotation), false);
            manager.Save();
        }
    }
}
